package com.stu.jvm;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * JVM垃圾回收详细演示
 * 涵盖：
 * - 垃圾回收基本概念
 * - 垃圾回收算法（标记-清除、复制、标记-整理、分代收集）
 * - 垃圾收集器类型（Serial、Parallel、CMS、G1、ZGC等）
 * - GC性能监控和调优
 * - 内存泄漏检测
 * - 引用类型（强、软、弱、虚引用）
 * 
 * @author 学习者
 * @version 1.0
 */
public class GarbageCollectionDemo {
    
    // 用于演示的静态集合
    private static List<Object> staticList = new ArrayList<>();
    
    // 用于演示内存泄漏的集合
    private static List<byte[]> memoryLeakList = new ArrayList<>();
    
    public static void main(String[] args) {
        System.out.println("=== JVM垃圾回收详细演示 ===");
        
        // 1. 垃圾回收基本概念
        demonstrateGCBasics();
        
        // 2. 对象可达性分析
        demonstrateReachabilityAnalysis();
        
        // 3. 垃圾回收算法
        demonstrateGCAlgorithms();
        
        // 4. 分代收集机制
        demonstrateGenerationalGC();
        
        // 5. 垃圾收集器类型
        demonstrateGCCollectors();
        
        // 6. GC性能监控
        demonstrateGCMonitoring();
        
        // 7. 引用类型演示
        demonstrateReferenceTypes();
        
        // 8. 内存泄漏演示
        demonstrateMemoryLeak();
        
        // 9. GC调优建议
        demonstrateGCTuning();
        
        // 10. 手动触发GC演示
        demonstrateManualGC();
    }
    
    /**
     * 垃圾回收基本概念演示
     */
    private static void demonstrateGCBasics() {
        System.out.println("\n=== 垃圾回收基本概念 ===");
        
        System.out.println("\n什么是垃圾回收（Garbage Collection）？");
        System.out.println("垃圾回收是自动内存管理机制，用于回收不再使用的对象所占用的内存。");
        
        System.out.println("\n垃圾回收的目标：");
        System.out.println("1. 自动回收无用对象占用的内存");
        System.out.println("2. 避免内存泄漏");
        System.out.println("3. 提高内存利用率");
        System.out.println("4. 减少程序员的内存管理负担");
        
        System.out.println("\n什么对象需要被回收？");
        System.out.println("1. 不再被任何变量引用的对象");
        System.out.println("2. 循环引用但整体不可达的对象");
        System.out.println("3. 超出作用域的局部变量引用的对象");
        
        // 演示对象的生命周期
        System.out.println("\n对象生命周期演示：");
        
        // 创建对象
        String obj1 = new String("临时对象1");
        System.out.println("创建对象：" + obj1 + " -> 对象在堆中分配内存");
        
        // 对象引用
        String obj2 = obj1;
        System.out.println("引用赋值：obj2 = obj1 -> 两个引用指向同一个对象");
        
        // 取消引用
        obj1 = null;
        System.out.println("取消引用：obj1 = null -> 对象仍被obj2引用，不会被回收");
        
        obj2 = null;
        System.out.println("取消引用：obj2 = null -> 对象不再被引用，成为垃圾回收候选");
        
        System.out.println("\n垃圾回收的时机：");
        System.out.println("1. 堆内存不足时");
        System.out.println("2. 系统空闲时");
        System.out.println("3. 手动调用System.gc()时（仅建议，不保证执行）");
        System.out.println("4. 达到特定的GC触发条件时");
        
        System.out.println("\nGC的影响：");
        System.out.println("优点：");
        System.out.println("  - 自动内存管理，减少内存泄漏");
        System.out.println("  - 简化编程，提高开发效率");
        System.out.println("  - 提高程序稳定性");
        
        System.out.println("\n缺点：");
        System.out.println("  - GC过程会暂停程序执行（Stop The World）");
        System.out.println("  - 无法精确控制回收时机");
        System.out.println("  - 可能影响程序性能");
    }
    
    /**
     * 对象可达性分析演示
     */
    private static void demonstrateReachabilityAnalysis() {
        System.out.println("\n=== 对象可达性分析 ===");
        
        System.out.println("\n可达性分析算法：");
        System.out.println("通过一系列称为'GC Roots'的根对象作为起始点，");
        System.out.println("从这些节点开始向下搜索，搜索走过的路径称为引用链。");
        System.out.println("当一个对象到GC Roots没有任何引用链相连时，");
        System.out.println("则证明此对象是不可达的，可以被回收。");
        
        System.out.println("\nGC Roots包括：");
        System.out.println("1. 虚拟机栈中引用的对象（局部变量）");
        System.out.println("2. 方法区中静态属性引用的对象");
        System.out.println("3. 方法区中常量引用的对象");
        System.out.println("4. 本地方法栈中JNI引用的对象");
        System.out.println("5. JVM内部的引用（如系统类加载器）");
        System.out.println("6. 同步锁持有的对象");
        System.out.println("7. JMXBean、JVMTI中注册的回调、本地代码缓存等");
        
        // 演示可达性分析
        System.out.println("\n可达性分析演示：");
        
        // GC Root 1: 局部变量引用
        Object localRef = new Object();
        System.out.println("localRef -> Object: 可达（通过局部变量）");
        
        // GC Root 2: 静态变量引用
        staticList.add(new String("静态引用对象"));
        System.out.println("staticList -> String: 可达（通过静态变量）");
        
        // 创建引用链
        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        list1.add("对象A");
        list2.add("对象B");
        
        // 建立引用关系
        System.out.println("\n引用链演示：");
        System.out.println("localRef -> list1 -> String('对象A'): 可达");
        System.out.println("localRef -> list2 -> String('对象B'): 可达");
        
        // 断开引用
        list1 = null;
        System.out.println("list1 = null 后，String('对象A')变为不可达");
        
        // 循环引用演示
        System.out.println("\n循环引用处理：");
        Node node1 = new Node("节点1");
        Node node2 = new Node("节点2");
        node1.next = node2;
        node2.next = node1; // 形成循环引用
        
        System.out.println("创建循环引用：node1 <-> node2");
        
        node1 = null;
        node2 = null;
        System.out.println("断开外部引用后，循环引用的对象仍然不可达，会被回收");
        System.out.println("Java使用可达性分析，能正确处理循环引用问题");
        
        System.out.println("\n对象回收过程：");
        System.out.println("1. 可达性分析标记不可达对象");
        System.out.println("2. 检查对象是否重写了finalize()方法");
        System.out.println("3. 如果重写且未被调用过，放入F-Queue队列");
        System.out.println("4. 执行finalize()方法（可能重新变为可达）");
        System.out.println("5. 再次可达性分析，确定最终回收对象");
    }
    
    /**
     * 用于演示循环引用的节点类
     */
    private static class Node {
        String data;
        Node next;
        
        Node(String data) {
            this.data = data;
        }
        
        @Override
        public String toString() {
            return "Node{data='" + data + "'}";
        }
    }
    
    /**
     * 垃圾回收算法演示
     */
    private static void demonstrateGCAlgorithms() {
        System.out.println("\n=== 垃圾回收算法 ===");
        
        System.out.println("\n1. 标记-清除算法（Mark-Sweep）");
        System.out.println("工作原理：");
        System.out.println("  第一阶段：标记所有需要回收的对象");
        System.out.println("  第二阶段：清除被标记的对象");
        
        System.out.println("\n优点：");
        System.out.println("  - 实现简单");
        System.out.println("  - 不需要移动对象");
        
        System.out.println("\n缺点：");
        System.out.println("  - 效率不高（两次遍历）");
        System.out.println("  - 产生内存碎片");
        System.out.println("  - 可能导致大对象无法分配");
        
        System.out.println("\n适用场景：老年代回收");
        
        System.out.println("\n\n2. 复制算法（Copying）");
        System.out.println("工作原理：");
        System.out.println("  将内存分为两块相等的区域");
        System.out.println("  每次只使用其中一块");
        System.out.println("  GC时将存活对象复制到另一块");
        System.out.println("  清空当前使用的内存块");
        
        System.out.println("\n优点：");
        System.out.println("  - 效率高（一次遍历）");
        System.out.println("  - 没有内存碎片");
        System.out.println("  - 分配简单（指针碰撞）");
        
        System.out.println("\n缺点：");
        System.out.println("  - 内存利用率低（只能使用一半）");
        System.out.println("  - 存活对象多时效率低");
        
        System.out.println("\n适用场景：年轻代回收（对象存活率低）");
        
        System.out.println("\n\n3. 标记-整理算法（Mark-Compact）");
        System.out.println("工作原理：");
        System.out.println("  第一阶段：标记所有存活的对象");
        System.out.println("  第二阶段：将存活对象向内存一端移动");
        System.out.println("  第三阶段：清理边界外的内存");
        
        System.out.println("\n优点：");
        System.out.println("  - 没有内存碎片");
        System.out.println("  - 内存利用率高");
        System.out.println("  - 适合存活对象多的场景");
        
        System.out.println("\n缺点：");
        System.out.println("  - 需要移动对象，成本较高");
        System.out.println("  - 暂停时间较长");
        
        System.out.println("\n适用场景：老年代回收");
        
        System.out.println("\n\n4. 分代收集算法（Generational Collection）");
        System.out.println("基本思想：");
        System.out.println("  根据对象存活周期将内存分为几块");
        System.out.println("  不同代使用不同的回收算法");
        
        System.out.println("\n分代假说：");
        System.out.println("  1. 弱分代假说：绝大多数对象都是朝生夕灭的");
        System.out.println("  2. 强分代假说：熬过越多次垃圾收集的对象越难以消亡");
        System.out.println("  3. 跨代引用假说：跨代引用相对于同代引用来说仅占极少数");
        
        System.out.println("\n算法选择：");
        System.out.println("  年轻代：复制算法（对象存活率低）");
        System.out.println("  老年代：标记-清除或标记-整理算法（对象存活率高）");
        
        // 演示不同算法的性能特点
        demonstrateAlgorithmPerformance();
    }
    
    /**
     * 演示不同算法的性能特点
     */
    private static void demonstrateAlgorithmPerformance() {
        System.out.println("\n算法性能对比演示：");
        
        int objectCount = 10000;
        int survivalRate = 10; // 存活率10%
        
        System.out.println("\n假设场景：" + objectCount + "个对象，存活率" + survivalRate + "%");
        
        System.out.println("\n标记-清除算法：");
        System.out.println("  标记阶段：遍历" + objectCount + "个对象");
        System.out.println("  清除阶段：清除" + (objectCount * (100 - survivalRate) / 100) + "个对象");
        System.out.println("  结果：产生内存碎片，可能影响后续分配");
        
        System.out.println("\n复制算法：");
        System.out.println("  复制阶段：复制" + (objectCount * survivalRate / 100) + "个存活对象");
        System.out.println("  清除阶段：清空整个From区域");
        System.out.println("  结果：无内存碎片，但内存利用率只有50%");
        
        System.out.println("\n标记-整理算法：");
        System.out.println("  标记阶段：遍历" + objectCount + "个对象");
        System.out.println("  整理阶段：移动" + (objectCount * survivalRate / 100) + "个存活对象");
        System.out.println("  结果：无内存碎片，内存利用率100%，但移动成本高");
        
        System.out.println("\n算法选择原则：");
        System.out.println("1. 存活率低（<50%）：选择复制算法");
        System.out.println("2. 存活率高（>50%）：选择标记-整理算法");
        System.out.println("3. 内存充足且碎片可接受：选择标记-清除算法");
        System.out.println("4. 实际应用中通常采用分代收集，结合多种算法");
    }
    
    /**
     * 分代收集机制演示
     */
    private static void demonstrateGenerationalGC() {
        System.out.println("\n=== 分代收集机制 ===");
        
        System.out.println("\n分代收集的基本结构：");
        System.out.println("\n年轻代（Young Generation）：");
        System.out.println("  - Eden区：新对象分配的地方");
        System.out.println("  - Survivor区：分为From和To两个区域");
        System.out.println("  - 默认比例 Eden:Survivor:Survivor = 8:1:1");
        
        System.out.println("\n老年代（Old Generation）：");
        System.out.println("  - 存放长期存活的对象");
        System.out.println("  - 占用堆内存的大部分空间");
        
        System.out.println("\n对象分配和晋升过程：");
        
        // 模拟对象分配过程
        System.out.println("\n1. 新对象分配：");
        Object newObject = new Object();
        System.out.println("   new Object() -> 分配到Eden区");
        
        System.out.println("\n2. Eden区满时触发Minor GC：");
        System.out.println("   - 存活对象复制到Survivor区");
        System.out.println("   - 对象年龄设置为1");
        System.out.println("   - 清空Eden区");
        
        System.out.println("\n3. 后续Minor GC：");
        System.out.println("   - Survivor区对象年龄+1");
        System.out.println("   - 在From和To区之间复制");
        System.out.println("   - 年龄达到阈值（默认15）晋升到老年代");
        
        System.out.println("\n4. 特殊情况的晋升：");
        System.out.println("   - 大对象直接分配到老年代");
        System.out.println("   - Survivor区空间不足时直接晋升");
        System.out.println("   - 动态年龄判断：相同年龄对象大小超过Survivor一半时晋升");
        
        System.out.println("\n5. 老年代GC：");
        System.out.println("   - 老年代空间不足时触发Major GC");
        System.out.println("   - 可能同时回收年轻代（Full GC）");
        
        // 演示GC类型
        System.out.println("\nGC类型说明：");
        System.out.println("\nMinor GC（年轻代GC）：");
        System.out.println("  - 触发条件：Eden区满");
        System.out.println("  - 回收范围：年轻代");
        System.out.println("  - 频率：高");
        System.out.println("  - 耗时：短");
        
        System.out.println("\nMajor GC（老年代GC）：");
        System.out.println("  - 触发条件：老年代满或空间分配担保失败");
        System.out.println("  - 回收范围：老年代");
        System.out.println("  - 频率：低");
        System.out.println("  - 耗时：长");
        
        System.out.println("\nFull GC（全堆GC）：");
        System.out.println("  - 触发条件：老年代满、方法区满、手动调用System.gc()");
        System.out.println("  - 回收范围：整个堆+方法区");
        System.out.println("  - 频率：最低");
        System.out.println("  - 耗时：最长");
        
        System.out.println("\n空间分配担保：");
        System.out.println("Minor GC前，虚拟机会检查老年代最大可用连续空间");
        System.out.println("是否大于年轻代所有对象总空间：");
        System.out.println("  - 如果大于，Minor GC是安全的");
        System.out.println("  - 如果小于，检查HandlePromotionFailure设置");
        System.out.println("  - 允许担保失败，检查老年代可用空间是否大于历次晋升平均大小");
        System.out.println("  - 如果大于，尝试Minor GC（有风险）");
        System.out.println("  - 如果小于，进行Full GC");
    }
    
    /**
     * 垃圾收集器类型演示
     */
    private static void demonstrateGCCollectors() {
        System.out.println("\n=== 垃圾收集器类型 ===");
        
        System.out.println("\n垃圾收集器发展历程：");
        
        System.out.println("\n1. Serial收集器（串行收集器）");
        System.out.println("特点：");
        System.out.println("  - 单线程收集");
        System.out.println("  - 收集时必须暂停所有工作线程（Stop The World）");
        System.out.println("  - 简单高效，适合单CPU环境");
        System.out.println("适用场景：Client模式、桌面应用、内存较小的应用");
        System.out.println("JVM参数：-XX:+UseSerialGC");
        
        System.out.println("\n2. ParNew收集器（并行收集器）");
        System.out.println("特点：");
        System.out.println("  - Serial收集器的多线程版本");
        System.out.println("  - 多线程并行收集");
        System.out.println("  - 可以与CMS收集器配合工作");
        System.out.println("适用场景：Server模式、多CPU环境");
        System.out.println("JVM参数：-XX:+UseParNewGC");
        
        System.out.println("\n3. Parallel Scavenge收集器（并行回收收集器）");
        System.out.println("特点：");
        System.out.println("  - 多线程并行收集");
        System.out.println("  - 关注吞吐量（Throughput）");
        System.out.println("  - 自适应调节策略");
        System.out.println("适用场景：后台运算、不需要太多交互的任务");
        System.out.println("JVM参数：-XX:+UseParallelGC");
        
        System.out.println("\n4. Serial Old收集器");
        System.out.println("特点：");
        System.out.println("  - Serial收集器的老年代版本");
        System.out.println("  - 单线程，使用标记-整理算法");
        System.out.println("  - 作为CMS收集器的后备方案");
        
        System.out.println("\n5. Parallel Old收集器");
        System.out.println("特点：");
        System.out.println("  - Parallel Scavenge收集器的老年代版本");
        System.out.println("  - 多线程，使用标记-整理算法");
        System.out.println("  - 注重吞吐量");
        System.out.println("JVM参数：-XX:+UseParallelOldGC");
        
        System.out.println("\n6. CMS收集器（Concurrent Mark Sweep）");
        System.out.println("特点：");
        System.out.println("  - 并发收集、低停顿");
        System.out.println("  - 使用标记-清除算法");
        System.out.println("  - 以获取最短回收停顿时间为目标");
        System.out.println("工作过程：");
        System.out.println("  1. 初始标记（STW）：标记GC Roots直接关联的对象");
        System.out.println("  2. 并发标记：与用户线程并发执行，标记所有可达对象");
        System.out.println("  3. 重新标记（STW）：修正并发标记期间的变动");
        System.out.println("  4. 并发清除：与用户线程并发执行，清除垃圾对象");
        System.out.println("缺点：");
        System.out.println("  - 产生内存碎片");
        System.out.println("  - 并发执行占用CPU资源");
        System.out.println("  - 无法处理浮动垃圾");
        System.out.println("JVM参数：-XX:+UseConcMarkSweepGC");
        
        System.out.println("\n7. G1收集器（Garbage First）");
        System.out.println("特点：");
        System.out.println("  - 面向服务端应用的垃圾收集器");
        System.out.println("  - 低延迟、高吞吐量");
        System.out.println("  - 可预测的停顿时间");
        System.out.println("  - 不再区分年轻代和老年代");
        System.out.println("工作原理：");
        System.out.println("  - 将堆分为多个大小相等的Region");
        System.out.println("  - 每个Region可以是Eden、Survivor或Old");
        System.out.println("  - 优先回收垃圾最多的Region");
        System.out.println("适用场景：");
        System.out.println("  - 大内存应用（>6GB）");
        System.out.println("  - 要求低延迟的应用");
        System.out.println("  - 替代CMS收集器");
        System.out.println("JVM参数：-XX:+UseG1GC");
        
        System.out.println("\n8. ZGC收集器（Z Garbage Collector）");
        System.out.println("特点：");
        System.out.println("  - 超低延迟垃圾收集器");
        System.out.println("  - 停顿时间不超过10ms");
        System.out.println("  - 支持TB级别的堆内存");
        System.out.println("  - 使用染色指针技术");
        System.out.println("适用场景：");
        System.out.println("  - 对延迟极其敏感的应用");
        System.out.println("  - 大内存应用");
        System.out.println("JVM参数：-XX:+UseZGC（JDK11+）");
        
        System.out.println("\n9. Shenandoah收集器");
        System.out.println("特点：");
        System.out.println("  - 低延迟垃圾收集器");
        System.out.println("  - 与应用线程并发执行");
        System.out.println("  - 使用转发指针技术");
        System.out.println("JVM参数：-XX:+UseShenandoahGC");
        
        // 显示当前使用的垃圾收集器
        showCurrentGCCollectors();
    }
    
    /**
     * 显示当前使用的垃圾收集器
     */
    private static void showCurrentGCCollectors() {
        System.out.println("\n当前JVM使用的垃圾收集器：");
        
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            System.out.println("收集器名称：" + gcBean.getName());
            System.out.println("管理的内存池：" + java.util.Arrays.toString(gcBean.getMemoryPoolNames()));
            System.out.println("收集次数：" + gcBean.getCollectionCount());
            System.out.println("收集时间：" + gcBean.getCollectionTime() + "ms");
            System.out.println("是否有效：" + gcBean.isValid());
            System.out.println("---");
        }
        
        System.out.println("\n收集器选择建议：");
        System.out.println("1. 单CPU或小内存：Serial + Serial Old");
        System.out.println("2. 多CPU，关注吞吐量：Parallel Scavenge + Parallel Old");
        System.out.println("3. 多CPU，关注延迟：ParNew + CMS");
        System.out.println("4. 大内存，低延迟：G1");
        System.out.println("5. 超大内存，超低延迟：ZGC或Shenandoah");
    }
    
    /**
     * GC性能监控演示
     */
    private static void demonstrateGCMonitoring() {
        System.out.println("\n=== GC性能监控 ===");
        
        System.out.println("\nGC性能指标：");
        System.out.println("1. 吞吐量（Throughput）：应用程序运行时间 / (应用程序运行时间 + GC时间)");
        System.out.println("2. 延迟（Latency）：GC造成的应用暂停时间");
        System.out.println("3. 内存占用（Memory Footprint）：Java堆所占用的内存大小");
        
        // 获取GC统计信息
        System.out.println("\n当前GC统计信息：");
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        
        long totalCollections = 0;
        long totalCollectionTime = 0;
        
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            long collections = gcBean.getCollectionCount();
            long collectionTime = gcBean.getCollectionTime();
            
            if (collections > 0) {
                System.out.println(gcBean.getName() + ":");
                System.out.println("  收集次数：" + collections);
                System.out.println("  总收集时间：" + collectionTime + "ms");
                System.out.println("  平均收集时间：" + (collectionTime / collections) + "ms");
                
                totalCollections += collections;
                totalCollectionTime += collectionTime;
            }
        }
        
        System.out.println("\n总体GC统计：");
        System.out.println("总收集次数：" + totalCollections);
        System.out.println("总收集时间：" + totalCollectionTime + "ms");
        
        if (totalCollections > 0) {
            System.out.println("平均收集时间：" + (totalCollectionTime / totalCollections) + "ms");
        }
        
        // 内存使用情况
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        
        System.out.println("\n内存使用情况：");
        System.out.println("堆内存使用率：" + 
            String.format("%.2f%%", (double) heapUsage.getUsed() / heapUsage.getMax() * 100));
        
        System.out.println("\nGC监控工具：");
        System.out.println("1. 命令行工具：");
        System.out.println("   - jstat：查看GC统计信息");
        System.out.println("   - jmap：查看内存使用情况");
        System.out.println("   - jstack：查看线程堆栈");
        
        System.out.println("\n2. 可视化工具：");
        System.out.println("   - JVisualVM：JVM监控和分析");
        System.out.println("   - JProfiler：商业性能分析工具");
        System.out.println("   - MAT：内存分析工具");
        System.out.println("   - GCViewer：GC日志分析工具");
        
        System.out.println("\n3. 在线监控：");
        System.out.println("   - JMX：Java管理扩展");
        System.out.println("   - Micrometer：应用监控门面");
        System.out.println("   - Prometheus + Grafana：监控和可视化");
        
        System.out.println("\nGC日志分析：");
        System.out.println("启用GC日志的JVM参数：");
        System.out.println("-XX:+PrintGC                    # 打印GC信息");
        System.out.println("-XX:+PrintGCDetails             # 打印GC详细信息");
        System.out.println("-XX:+PrintGCTimeStamps          # 打印GC时间戳");
        System.out.println("-XX:+PrintGCApplicationStoppedTime # 打印应用暂停时间");
        System.out.println("-Xloggc:gc.log                  # GC日志文件");
    }
    
    /**
     * 引用类型演示
     */
    private static void demonstrateReferenceTypes() {
        System.out.println("\n=== 引用类型演示 ===");
        
        System.out.println("\nJava中的四种引用类型：");
        
        System.out.println("\n1. 强引用（Strong Reference）");
        System.out.println("特点：");
        System.out.println("  - 最常见的引用类型");
        System.out.println("  - 只要强引用存在，对象永远不会被回收");
        System.out.println("  - 宁愿抛出OutOfMemoryError也不回收");
        
        // 强引用演示
        Object strongRef = new Object();
        System.out.println("强引用示例：Object strongRef = new Object();");
        System.out.println("只要strongRef存在，对象就不会被回收");
        
        System.out.println("\n2. 软引用（Soft Reference）");
        System.out.println("特点：");
        System.out.println("  - 内存充足时不会被回收");
        System.out.println("  - 内存不足时会被回收");
        System.out.println("  - 适合实现内存敏感的缓存");
        
        System.out.println("\n软引用示例：");
        System.out.println("SoftReference<Object> softRef = new SoftReference<>(new Object());");
        System.out.println("Object obj = softRef.get(); // 获取对象，可能返回null");
        
        System.out.println("\n3. 弱引用（Weak Reference）");
        System.out.println("特点：");
        System.out.println("  - 下次GC时一定会被回收");
        System.out.println("  - 不影响对象的生命周期");
        System.out.println("  - 适合实现规范化映射");
        
        System.out.println("\n弱引用示例：");
        System.out.println("WeakReference<Object> weakRef = new WeakReference<>(new Object());");
        System.out.println("Object obj = weakRef.get(); // 获取对象，GC后可能返回null");
        
        System.out.println("\n4. 虚引用（Phantom Reference）");
        System.out.println("特点：");
        System.out.println("  - 无法通过虚引用获取对象");
        System.out.println("  - 必须与引用队列配合使用");
        System.out.println("  - 用于跟踪对象被回收的状态");
        System.out.println("  - 可以替代finalize()方法");
        
        System.out.println("\n虚引用示例：");
        System.out.println("ReferenceQueue<Object> queue = new ReferenceQueue<>();");
        System.out.println("PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);");
        System.out.println("phantomRef.get(); // 总是返回null");
        
        System.out.println("\n引用队列（Reference Queue）：");
        System.out.println("作用：");
        System.out.println("  - 当引用对象被回收时，引用本身会被加入队列");
        System.out.println("  - 可以通过队列监控对象回收状态");
        System.out.println("  - 用于清理相关资源");
        
        System.out.println("\n引用类型的应用场景：");
        System.out.println("\n强引用：");
        System.out.println("  - 普通对象引用");
        System.out.println("  - 必须存在的对象");
        
        System.out.println("\n软引用：");
        System.out.println("  - 图片缓存");
        System.out.println("  - 网页缓存");
        System.out.println("  - 内存敏感的缓存系统");
        
        System.out.println("\n弱引用：");
        System.out.println("  - WeakHashMap");
        System.out.println("  - ThreadLocal的实现");
        System.out.println("  - 监听器模式（避免内存泄漏）");
        
        System.out.println("\n虚引用：");
        System.out.println("  - 对象回收监控");
        System.out.println("  - 堆外内存管理");
        System.out.println("  - 资源清理（替代finalize）");
        
        System.out.println("\n引用类型与GC的关系：");
        System.out.println("GC回收顺序：虚引用 > 弱引用 > 软引用 > 强引用");
        System.out.println("只有强引用能阻止对象被回收");
        System.out.println("其他引用类型都不能阻止对象被回收");
    }
    
    /**
     * 内存泄漏演示
     */
    private static void demonstrateMemoryLeak() {
        System.out.println("\n=== 内存泄漏演示 ===");
        
        System.out.println("\n什么是内存泄漏？");
        System.out.println("内存泄漏是指程序中已动态分配的堆内存由于某种原因");
        System.out.println("未释放或无法释放，造成系统内存的浪费。");
        
        System.out.println("\nJava中的内存泄漏特点：");
        System.out.println("虽然有GC自动回收，但仍可能发生内存泄漏：");
        System.out.println("  - 对象无法被GC回收");
        System.out.println("  - 长期持有不需要的对象引用");
        System.out.println("  - 逻辑上的内存泄漏");
        
        System.out.println("\n常见的内存泄漏场景：");
        
        System.out.println("\n1. 静态集合类引起的内存泄漏");
        System.out.println("问题代码示例：");
        System.out.println("static List<Object> list = new ArrayList<>();");
        System.out.println("list.add(new Object()); // 对象永远不会被回收");
        
        // 演示静态集合内存泄漏（注释掉避免真正泄漏）
        // staticList.add(new byte[1024 * 1024]); // 1MB对象
        System.out.println("\n解决方案：");
        System.out.println("  - 及时清理不需要的元素");
        System.out.println("  - 使用弱引用集合");
        System.out.println("  - 避免使用静态集合");
        
        System.out.println("\n2. 监听器和回调未移除");
        System.out.println("问题：");
        System.out.println("  - 注册监听器后未移除");
        System.out.println("  - 匿名内部类持有外部类引用");
        System.out.println("解决方案：");
        System.out.println("  - 及时移除监听器");
        System.out.println("  - 使用弱引用");
        System.out.println("  - 使用静态内部类");
        
        System.out.println("\n3. 单例模式引起的内存泄漏");
        System.out.println("问题：");
        System.out.println("  - 单例对象持有其他对象引用");
        System.out.println("  - 单例生命周期与应用相同");
        System.out.println("解决方案：");
        System.out.println("  - 及时清理单例中的引用");
        System.out.println("  - 使用弱引用或软引用");
        
        System.out.println("\n4. 数据库连接、IO流未关闭");
        System.out.println("问题：");
        System.out.println("  - 连接对象未正确关闭");
        System.out.println("  - 资源泄漏导致内存泄漏");
        System.out.println("解决方案：");
        System.out.println("  - 使用try-with-resources");
        System.out.println("  - 在finally块中关闭资源");
        
        System.out.println("\n5. ThreadLocal使用不当");
        System.out.println("问题：");
        System.out.println("  - ThreadLocal变量未清理");
        System.out.println("  - 线程池中线程复用导致泄漏");
        System.out.println("解决方案：");
        System.out.println("  - 使用后调用remove()方法");
        System.out.println("  - 使用try-finally确保清理");
        
        System.out.println("\n6. 缓存使用不当");
        System.out.println("问题：");
        System.out.println("  - 缓存无限增长");
        System.out.println("  - 缓存项永不过期");
        System.out.println("解决方案：");
        System.out.println("  - 设置缓存大小限制");
        System.out.println("  - 设置过期时间");
        System.out.println("  - 使用LRU等淘汰策略");
        
        System.out.println("\n内存泄漏检测方法：");
        System.out.println("1. 监控工具：");
        System.out.println("   - JVisualVM");
        System.out.println("   - JProfiler");
        System.out.println("   - MAT（Memory Analyzer Tool）");
        
        System.out.println("\n2. 命令行工具：");
        System.out.println("   - jmap：生成堆转储文件");
        System.out.println("   - jstat：监控GC和内存使用");
        
        System.out.println("\n3. 代码分析：");
        System.out.println("   - 静态代码分析工具");
        System.out.println("   - Code Review");
        System.out.println("   - 单元测试");
        
        System.out.println("\n预防内存泄漏的最佳实践：");
        System.out.println("1. 及时释放不需要的对象引用");
        System.out.println("2. 避免创建不必要的对象");
        System.out.println("3. 正确使用集合类");
        System.out.println("4. 合理使用缓存");
        System.out.println("5. 正确处理监听器和回调");
        System.out.println("6. 及时关闭资源");
        System.out.println("7. 定期进行内存分析");
    }
    
    /**
     * GC调优建议演示
     */
    private static void demonstrateGCTuning() {
        System.out.println("\n=== GC调优建议 ===");
        
        System.out.println("\nGC调优的目标：");
        System.out.println("1. 降低GC频率");
        System.out.println("2. 减少GC停顿时间");
        System.out.println("3. 提高应用吞吐量");
        System.out.println("4. 避免内存溢出");
        
        System.out.println("\nGC调优的原则：");
        System.out.println("1. 大多数对象朝生夕灭");
        System.out.println("2. 减少对象创建");
        System.out.println("3. 合理设置堆大小");
        System.out.println("4. 选择合适的垃圾收集器");
        
        System.out.println("\n堆内存调优参数：");
        System.out.println("-Xms<size>          # 初始堆大小");
        System.out.println("-Xmx<size>          # 最大堆大小");
        System.out.println("-Xmn<size>          # 年轻代大小");
        System.out.println("-XX:NewRatio=n      # 老年代/年轻代比例");
        System.out.println("-XX:SurvivorRatio=n # Eden/Survivor比例");
        System.out.println("-XX:MaxTenuringThreshold=n # 晋升年龄阈值");
        
        System.out.println("\n垃圾收集器选择参数：");
        System.out.println("-XX:+UseSerialGC           # 使用Serial收集器");
        System.out.println("-XX:+UseParallelGC         # 使用Parallel收集器");
        System.out.println("-XX:+UseConcMarkSweepGC    # 使用CMS收集器");
        System.out.println("-XX:+UseG1GC               # 使用G1收集器");
        System.out.println("-XX:+UseZGC                # 使用ZGC收集器");
        
        System.out.println("\nGC性能调优参数：");
        System.out.println("-XX:ParallelGCThreads=n    # 并行GC线程数");
        System.out.println("-XX:MaxGCPauseMillis=n     # 最大GC停顿时间");
        System.out.println("-XX:GCTimeRatio=n          # GC时间比例");
        System.out.println("-XX:+UseAdaptiveSizePolicy # 自适应大小策略");
        
        System.out.println("\nG1收集器特有参数：");
        System.out.println("-XX:G1HeapRegionSize=n     # Region大小");
        System.out.println("-XX:G1NewSizePercent=n     # 年轻代最小比例");
        System.out.println("-XX:G1MaxNewSizePercent=n  # 年轻代最大比例");
        System.out.println("-XX:G1MixedGCCountTarget=n # Mixed GC目标次数");
        
        System.out.println("\nGC调优步骤：");
        System.out.println("\n1. 分析应用特点");
        System.out.println("   - 对象生命周期");
        System.out.println("   - 内存使用模式");
        System.out.println("   - 性能要求（吞吐量 vs 延迟）");
        
        System.out.println("\n2. 选择合适的垃圾收集器");
        System.out.println("   - 单CPU：Serial");
        System.out.println("   - 多CPU + 高吞吐量：Parallel");
        System.out.println("   - 多CPU + 低延迟：G1或CMS");
        System.out.println("   - 超大堆 + 超低延迟：ZGC");
        
        System.out.println("\n3. 设置合理的堆大小");
        System.out.println("   - 初始堆大小 = 最大堆大小（避免动态扩展）");
        System.out.println("   - 堆大小 = 应用峰值内存 * 1.5 ~ 2");
        System.out.println("   - 年轻代 = 堆大小 * 1/3 ~ 1/4");
        
        System.out.println("\n4. 监控和分析");
        System.out.println("   - 启用GC日志");
        System.out.println("   - 监控GC频率和停顿时间");
        System.out.println("   - 分析内存使用模式");
        
        System.out.println("\n5. 迭代优化");
        System.out.println("   - 根据监控结果调整参数");
        System.out.println("   - 压力测试验证效果");
        System.out.println("   - 持续监控和优化");
        
        System.out.println("\n常见调优场景：");
        
        System.out.println("\n场景1：Minor GC频繁");
        System.out.println("原因：年轻代过小");
        System.out.println("解决：增大年轻代大小");
        
        System.out.println("\n场景2：Full GC频繁");
        System.out.println("原因：老年代过小或内存泄漏");
        System.out.println("解决：增大老年代或排查内存泄漏");
        
        System.out.println("\n场景3：GC停顿时间过长");
        System.out.println("原因：堆过大或收集器不合适");
        System.out.println("解决：减小堆大小或更换收集器");
        
        System.out.println("\n场景4：吞吐量不足");
        System.out.println("原因：GC时间占比过高");
        System.out.println("解决：优化代码减少对象创建或调整GC参数");
        
        System.out.println("\nGC调优注意事项：");
        System.out.println("1. 不要过早优化");
        System.out.println("2. 基于实际测试数据调优");
        System.out.println("3. 一次只调整一个参数");
        System.out.println("4. 记录调优前后的性能数据");
        System.out.println("5. 在生产环境验证效果");
        
        System.out.println("\n代码层面的优化建议：");
        System.out.println("1. 对象池技术：复用对象，减少创建");
        System.out.println("2. 合理使用StringBuilder：避免字符串拼接创建临时对象");
        System.out.println("3. 集合预分配：指定初始容量，避免扩容");
        System.out.println("4. 避免在循环中创建对象");
        System.out.println("5. 及时释放大对象引用");
        System.out.println("6. 使用基本类型而非包装类型");
    }
    
    /**
     * 手动触发GC演示
     */
    private static void demonstrateManualGC() {
        System.out.println("\n=== 手动触发GC演示 ===");
        
        System.out.println("\n手动GC的方法：");
        System.out.println("1. System.gc()：建议JVM进行垃圾回收");
        System.out.println("2. Runtime.getRuntime().gc()：同System.gc()");
        
        System.out.println("\n注意事项：");
        System.out.println("- 这些方法只是建议，JVM可能忽略");
        System.out.println("- 可以通过-XX:+DisableExplicitGC禁用");
        System.out.println("- 不建议在生产环境频繁调用");
        System.out.println("- 可能导致不必要的性能开销");
        
        // 记录GC前的状态
        System.out.println("\nGC前内存状态：");
        showMemoryStatus();
        
        // 创建一些对象
        System.out.println("\n创建临时对象...");
        List<Object> tempList = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            tempList.add(new Object());
        }
        
        System.out.println("\n创建对象后内存状态：");
        showMemoryStatus();
        
        // 清除引用
        tempList = null;
        
        System.out.println("\n清除引用后，手动触发GC...");
        
        // 记录GC统计信息
        long gcCountBefore = getTotalGCCount();
        long gcTimeBefore = getTotalGCTime();
        
        // 手动触发GC
        System.gc();
        
        // 等待GC完成
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("\nGC后内存状态：");
        showMemoryStatus();
        
        // 显示GC统计变化
        long gcCountAfter = getTotalGCCount();
        long gcTimeAfter = getTotalGCTime();
        
        System.out.println("\nGC统计变化：");
        System.out.println("GC次数增加：" + (gcCountAfter - gcCountBefore));
        System.out.println("GC时间增加：" + (gcTimeAfter - gcTimeBefore) + "ms");
        
        System.out.println("\n何时可以手动调用GC：");
        System.out.println("1. 应用空闲期间");
        System.out.println("2. 大批量数据处理完成后");
        System.out.println("3. 内存使用达到阈值时");
        System.out.println("4. 测试和调试阶段");
        
        System.out.println("\n替代方案：");
        System.out.println("1. 优化代码，减少垃圾产生");
        System.out.println("2. 调整GC参数，让JVM自动优化");
        System.out.println("3. 使用内存监控，及时发现问题");
        System.out.println("4. 合理设计对象生命周期");
    }
    
    /**
     * 显示内存状态
     */
    private static void showMemoryStatus() {
        Runtime runtime = Runtime.getRuntime();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        long maxMemory = runtime.maxMemory();
        
        System.out.println("总内存：" + formatBytes(totalMemory));
        System.out.println("已用内存：" + formatBytes(usedMemory));
        System.out.println("空闲内存：" + formatBytes(freeMemory));
        System.out.println("最大内存：" + formatBytes(maxMemory));
        System.out.println("内存使用率：" + String.format("%.2f%%", (double) usedMemory / totalMemory * 100));
    }
    
    /**
     * 获取总GC次数
     */
    private static long getTotalGCCount() {
        long totalCount = 0;
        for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
            long count = gcBean.getCollectionCount();
            if (count > 0) {
                totalCount += count;
            }
        }
        return totalCount;
    }
    
    /**
     * 获取总GC时间
     */
    private static long getTotalGCTime() {
        long totalTime = 0;
        for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
            long time = gcBean.getCollectionTime();
            if (time > 0) {
                totalTime += time;
            }
        }
        return totalTime;
    }
    
    /**
     * 格式化字节数为可读格式
     */
    private static String formatBytes(long bytes) {
        if (bytes < 0) return "未知";
        
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double size = bytes;
        
        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }
        
        return String.format("%.2f %s", size, units[unitIndex]);
    }
}